Added gtkstatusicon-quartz.c Implements the quartz backend for the status
authorMikael Hallendal <micke@imendio.com>
Wed, 20 Dec 2006 13:24:05 +0000 (13:24 +0000)
committerMikael Hallendal <hallski@src.gnome.org>
Wed, 20 Dec 2006 13:24:05 +0000 (13:24 +0000)
2006-12-20  Mikael Hallendal  <micke@imendio.com>

* gtk/Makefile.am: Added gtkstatusicon-quartz.c
* gtk/gtkstatusicon-quartz.c: Implements the quartz backend for the
status icon.
* gtk/gtkstatusicon.c: Hooked in the new quartz backend. Bug #387874.

ChangeLog
gtk/Makefile.am
gtk/gtkstatusicon-quartz.c [new file with mode: 0644]
gtk/gtkstatusicon.c

index ec8234622e9af755e796078e273958c9ad925031..59053d1fc28fd626889405d4a0bbe45211a042f1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-12-20  Mikael Hallendal  <micke@imendio.com>
+
+       * gtk/Makefile.am: Added gtkstatusicon-quartz.c
+       * gtk/gtkstatusicon-quartz.c: Implements the quartz backend for the
+       status icon.
+       * gtk/gtkstatusicon.c: Hooked in the new quartz backend. Bug #387874.
+
 2006-12-19  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkprintunixdialog.c: Add a tooltip explaining the
index 4c07d1e46185276f18eda9d09bac1b36ee8d21b5..36ad0292cbd22ff5c7eb88cf4423044a8fca163a 100644 (file)
@@ -697,6 +697,7 @@ gtk_extra_sources =                         \
        paper_names.c                           \
        paper_names_offsets.c                   \
        gen-paper-names.c                       \
+       gtkstatusicon-quartz.c                  \
        gtk.symbols                             \
        gtkversion.h.in                         \
        gtkmarshalers.list                      \
diff --git a/gtk/gtkstatusicon-quartz.c b/gtk/gtkstatusicon-quartz.c
new file mode 100644 (file)
index 0000000..8f8bb02
--- /dev/null
@@ -0,0 +1,148 @@
+/* gtkstatusicon-quartz.c:
+ *
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * GCC on Mac OS X handles inlined objective C in C-files.
+ *
+ * Authors:
+ *  Mikael Hallendal <micke@imendio.com>
+ */
+
+#import <Cocoa/Cocoa.h>
+#include <quartz/gdkquartz.h>
+
+#define QUARTZ_POOL_ALLOC NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
+#define QUARTZ_POOL_RELEASE [pool release]
+
+@interface GtkQuartzStatusIcon : NSObject 
+{
+  GtkStatusIcon *status_icon;
+  NSStatusBar   *ns_bar;
+  NSStatusItem  *ns_item;
+  NSImage       *current_image;
+  NSString      *ns_tooltip;
+}
+- (id) initWithStatusIcon:(GtkStatusIcon *)status_icon;
+- (void) ensureItem;
+- (void) actionCb:(NSObject *)button;
+- (void) setImage:(GdkPixbuf *)pixbuf;
+- (void) setVisible:(gboolean)visible;
+- (void) setToolTip:(const gchar *)tooltip_text;
+- (float) getWidth;
+- (float) getHeight;
+@end
+
+@implementation GtkQuartzStatusIcon : NSObject
+- (id) initWithStatusIcon:(GtkStatusIcon *)icon
+{
+  [super init];
+  status_icon = icon;
+  ns_bar = [NSStatusBar systemStatusBar];
+
+  return self;
+}
+
+- (void) ensureItem
+{
+  if (ns_item != nil)
+    return;
+
+  ns_item = [ns_bar statusItemWithLength:NSVariableStatusItemLength];
+  [ns_item setAction:@selector(actionCb:)];
+  [ns_item setTarget:self];
+  [ns_item retain];
+}
+
+- (void) dealloc
+{
+  g_print ("Deallocating GtkQuartzStatusIcon\n");
+  [current_image release];
+  [ns_item release];
+  [ns_bar release];
+
+  [super dealloc];
+}
+
+- (void) actionCb:(NSObject *)button
+{ 
+  NSEvent *event = [NSApp currentEvent];
+  double time = [event timestamp];
+  
+  g_signal_emit (status_icon,
+                 status_icon_signals [POPUP_MENU_SIGNAL], 0,
+                 1,
+                 time * 1000.0);
+}
+
+- (void) setImage:(GdkPixbuf *)pixbuf
+{
+  /* Support NULL */
+  [self ensureItem];
+
+  if (current_image != nil) {
+    [current_image release];
+    current_image = nil;
+  }
+  
+  if (!pixbuf) {
+    [ns_item release];
+    ns_item = nil;
+    return;
+  }
+
+  current_image = gdk_quartz_pixbuf_to_ns_image_libgtk_only (pixbuf);
+  [current_image retain];
+
+  [ns_item setImage:current_image];
+}
+
+- (void) setVisible:(gboolean)visible
+{
+  if (visible) {
+    [self ensureItem];
+    if (ns_item != nil)
+      [ns_item setImage:current_image];
+    if (ns_tooltip != nil)
+      [ns_item setToolTip:ns_tooltip];
+  } else {
+    [ns_item release];
+    ns_item = nil;
+  }
+}
+
+- (void) setToolTip:(const gchar *)tooltip_text
+{
+  [ns_tooltip release];
+  ns_tooltip = [[NSString stringWithUTF8String:tooltip_text] retain];
+  
+  [ns_item setToolTip:ns_tooltip];
+}
+
+- (float) getWidth
+{
+  return [ns_bar thickness];
+}
+
+- (float) getHeight
+{
+  return [ns_bar thickness];
+}
+@end
+
+
+
index 7ed3cb754abd84506b673131f507446376143843..047fd48df1357051c1da022f2e05450fd53734ef 100755 (executable)
@@ -3,6 +3,7 @@
  * Copyright (C) 2003 Sun Microsystems, Inc.
  * Copyright (C) 2005 Hans Breuer <hans@breuer.org>
  * Copyright (C) 2005 Novell, Inc.
+ * Copyright (C) 2006 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -23,6 +24,7 @@
  *     Mark McLoughlin <mark@skynet.ie>
  *     Hans Breuer <hans@breuer.org>
  *     Tor Lillqvist <tml@novell.com>
+ *     Mikael Hallendal <micke@imendio.com>
  */
 
 #include <config.h>
 #define WM_GTK_TRAY_NOTIFICATION (WM_USER+1)
 #endif
 
+#ifdef GDK_WINDOWING_QUARTZ
+#include "gtkicontheme.h"
+#include "gtklabel.h"
+#endif 
+
 #include "gtkalias.h"
 
 #define BLINK_TIMEOUT 500
@@ -73,6 +80,12 @@ enum
   LAST_SIGNAL
 };
 
+static guint status_icon_signals [LAST_SIGNAL] = { 0 };
+
+#ifdef GDK_WINDOWING_QUARTZ
+#include "gtkstatusicon-quartz.c"
+#endif
+
 struct _GtkStatusIconPrivate
 {
 #ifdef GDK_WINDOWING_X11
@@ -85,6 +98,11 @@ struct _GtkStatusIconPrivate
   GtkWidget     *dummy_widget;
   NOTIFYICONDATAW nid;
 #endif
+       
+#ifdef GDK_WINDOWING_QUARTZ
+  GtkWidget     *dummy_widget;
+  GtkQuartzStatusIcon *status_item;
+#endif
 
   gint          size;
 
@@ -130,8 +148,6 @@ static void     gtk_status_icon_disable_blinking (GtkStatusIcon  *status_icon);
 static void     gtk_status_icon_reset_image_data (GtkStatusIcon  *status_icon);
                                           
 
-static guint status_icon_signals [LAST_SIGNAL] = { 0 };
-
 G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT)
 
 static void
@@ -466,6 +482,20 @@ gtk_status_icon_init (GtkStatusIcon *status_icon)
       priv->nid.hWnd = NULL;
     }
 #endif
+       
+#ifdef GDK_WINDOWING_QUARTZ
+  priv->dummy_widget = gtk_label_new ("");
+
+  QUARTZ_POOL_ALLOC;
+
+  priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon];
+
+  priv->image_height = [priv->status_item getHeight];
+  priv->image_width = [priv->status_item getWidth];
+
+  QUARTZ_POOL_RELEASE;
+
+#endif 
 }
 
 static void
@@ -496,6 +526,12 @@ gtk_status_icon_finalize (GObject *object)
 
   gtk_widget_destroy (priv->dummy_widget);
 #endif
+       
+#ifdef GDK_WINDOWING_QUARTZ
+  QUARTZ_POOL_ALLOC;
+  [priv->status_item release];
+  QUARTZ_POOL_RELEASE;
+#endif
 
   G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
 }
@@ -815,6 +851,11 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
       if (priv->nid.hWnd != NULL && priv->visible)
        if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
          g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+      QUARTZ_POOL_ALLOC;
+      [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)];
+      QUARTZ_POOL_RELEASE;
 #endif
       return;
     }
@@ -857,6 +898,12 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
              if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
                  g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
 #endif
+#ifdef GDK_WINDOWING_QUARTZ
+      QUARTZ_POOL_ALLOC;
+      [priv->status_item setImage:scaled];
+      QUARTZ_POOL_RELEASE;
+#endif
+                       
            g_object_unref (scaled);
          }
        else
@@ -869,6 +916,9 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
            if (priv->nid.hWnd != NULL && priv->visible)
              if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
                g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+      [priv->status_item setImage:NULL];
 #endif
          }
       }
@@ -896,6 +946,20 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
              g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
          g_object_unref (pixbuf);
        }
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+       {
+         GdkPixbuf *pixbuf;
+
+         pixbuf = gtk_widget_render_icon (priv->dummy_widget,
+                                          priv->image_data.stock_id,
+                                          GTK_ICON_SIZE_SMALL_TOOLBAR,
+                                          NULL);
+         QUARTZ_POOL_ALLOC;
+         [priv->status_item setImage:pixbuf];
+         QUARTZ_POOL_RELEASE;
+         g_object_unref (pixbuf);
+       }       
 #endif
       }
       break;
@@ -924,6 +988,22 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
          g_object_unref (pixbuf);
        }
 #endif
+#ifdef GDK_WINDOWING_QUARTZ
+       {
+         GdkPixbuf *pixbuf;
+
+         pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                            priv->image_data.icon_name,
+                                            priv->size,
+                                            0, NULL);
+
+         QUARTZ_POOL_ALLOC;
+         [priv->status_item setImage:pixbuf];
+         QUARTZ_POOL_RELEASE;
+         g_object_unref (pixbuf);
+       }
+#endif
+       
       }
       break;
       
@@ -936,6 +1016,13 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon)
       if (priv->nid.hWnd != NULL && priv->visible)
        if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
          g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+        {
+          QUARTZ_POOL_ALLOC;
+          [priv->status_item setImage:NULL];
+          QUARTZ_POOL_RELEASE;
+        }
 #endif
       break;
     default:
@@ -1398,6 +1485,11 @@ gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
     if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
       g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
 #endif
+#ifdef GDK_WINDOWING_QUARTZ
+  QUARTZ_POOL_ALLOC;
+  [priv->status_item setToolTip:tooltip_text];
+  QUARTZ_POOL_RELEASE;
+#endif
 }
 
 static gboolean
@@ -1482,6 +1574,11 @@ gtk_status_icon_set_visible (GtkStatusIcon *status_icon,
          else
            Shell_NotifyIconW (NIM_DELETE, &priv->nid);
        }
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+      QUARTZ_POOL_ALLOC;
+      [priv->status_item setVisible:visible];
+      QUARTZ_POOL_RELEASE;
 #endif
       g_object_notify (G_OBJECT (status_icon), "visible");
     }
@@ -1596,6 +1693,9 @@ gtk_status_icon_is_embedded (GtkStatusIcon *status_icon)
 #ifdef GDK_WINDOWING_WIN32
   return TRUE;
 #endif
+#ifdef GDK_WINDOWING_QUARTZ
+  return TRUE;
+#endif
 }
 
 /**